package org.coder.consumer_sentinel_9005.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import jakarta.annotation.Resource;
import org.coder.consumer_sentinel_9005.service.WebLinkService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/stream")
public class StreamController implements InitializingBean {
    //流控模式--链路模式
    @Resource
    WebLinkService webLinkService;
    @GetMapping("/chainA")
    public String chainA(){
        return webLinkService.testChain() + ": chainA";
    }
    @GetMapping("/chainB")
    public String chainB(){
        return webLinkService.testChain() + ": chainB";
    }

    //流控模式--关联模式
    @GetMapping("/readdb")
    public String readDb(){
        return "readDb";
    }
    @GetMapping("/writedb")
    public String writeDb(){
        return "writeDb";
    }


    //统一异常方式
    @GetMapping("/unify") //控制台设置流控规则
    public String testUnify() {
        return "testUnify";
    }

    //并发线程控制
    @GetMapping("/thread")
    @SentinelResource(value = "thread",
            blockHandlerClass = SentinelBlockHandler.class,
            blockHandler = "sentinelThreadBlockHandler")
    public String thread() {
        return "thread ";
    }

    //代码实现流控-qps,抛异常方式
    @GetMapping("/exception")
    public String test() {
        Entry entry = null;
        try {
            entry = SphU.entry("exception");

            return "test";
        } catch (BlockException e) {
            /*
                BlockException是流控异常，当达到流控阈值时，会抛出该异常
                 实现类：
                    FlowException 流控异常
                    DegradeException 降级异常
                    ParamFlowException 参数流控异常
                    SystemBlockException 系统负载异常
                    AuthorityException 授权异常
            * */
            return "被限流";
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }

    //bool方式
    @GetMapping("/bool")
    public String testBool() {
        if (SphO.entry("bool")) {
            try {
                return "test";
            } finally {
                SphO.exit();
            }
        } else {
            return "被限流bool";
        }
    }

    //注解方式
    @GetMapping("/sentinel")
    @SentinelResource(value = "sentinel", blockHandler = "sentinelBlockHandler")
    public String testSentinel() {//参数和blockHandler方法参数一致,返回值和blockHandler方法返回值一致
        return "testSentinel";
    }

    public String sentinelBlockHandler(BlockException e) {
        return "被限流sentinel";
    }

    @GetMapping("/sentinelClass")
    @SentinelResource(value = "sentinel",
            blockHandlerClass = SentinelBlockHandler.class,
            blockHandler = "sentinelBlockHandler")
    public String testSentinelClass() {//参数和blockHandler方法参数一致,返回值和blockHandler方法返回值一致
        return "testSentinelClass";
    }


    //流控规则代码实现参考Sentinel.docx
    //也可以控制台设置流控规则
//    @PostConstruct //重启服务控制不显示
    private void initFlowQpsRule() {
        //异常方式
        List<FlowRule> rules = new ArrayList<>();//流控规则列表
        FlowRule rule = new FlowRule("exception");//流控规则,test为资源名
        rule.setCount(2);//阈值
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);//QPS限流
        rule.setLimitApp("default");//默认，对所有的入口流量生效
        rules.add(rule);
        //bool方式
        FlowRule rulebool = new FlowRule("bool");//流控规则,test为资源名
        rulebool.setCount(2);//阈值
        rulebool.setGrade(RuleConstant.FLOW_GRADE_QPS);//QPS限流
        rulebool.setLimitApp("default");//默认，对所有的入口流量生效
        rules.add(rulebool);
        //@SentinelResource注解方式
        FlowRule rulesentinel = new FlowRule("sentinel");//流控规则
        rulesentinel.setCount(2);//阈值
        rulesentinel.setGrade(RuleConstant.FLOW_GRADE_QPS);//QPS限流
        rulesentinel.setLimitApp("default");//默认，对所有的入口流量生效
        rules.add(rulesentinel);

        //@SentinelResource注解方式，并发线程控制
        FlowRule thread = new FlowRule("thread");
        thread.setCount(1);//阈值
        thread.setGrade(RuleConstant.FLOW_GRADE_THREAD);//线程数限流
        thread.setLimitApp("default");//默认，对所有的入口流量生效
        rules.add(thread);

        FlowRuleManager.loadRules(rules);

        /*
            RuleConstant
                FLOW_GRADE_QPS  QPS限流
                FLOW_GRADE_THREAD  线程数限流
                FLOW_GRADE_RT  响应时间限流
                FLOW_GRADE_CONCURRENCY  并发数限流
        * */
    }

    @Override
    public void afterPropertiesSet() throws Exception {
//        initFlowQpsRule();
    }
}

